"""
提醒服务模块
负责多线程后台提醒服务，定时检查需要提醒的日程
使用多线程技术，避免阻塞主界面
"""
import threading
import time
import logging
from datetime import datetime, timedelta
import sys
import os
import shutil

import math  # 用于声音生成
# import numpy  # 用于声音生成（如果可用）

class ReminderService:
    """
    提醒服务类
    在后台线程中运行，定期检查需要提醒的日程
    """
    
    def __init__(self, db_manager, gui_callback=None):
        self.db_manager = db_manager
        self.gui_callback = gui_callback  # 用于通知GUI显示提醒
        self.is_running = False
        self.check_interval = 30  # 检查间隔(秒)
        self.reminder_thread = None
        self.logger = logging.getLogger(__name__)
        self.pending_reminders = set()  # 记录已触发但未处理的提醒
        
        # 提醒声音配置
        self.sound_enabled = True
        self.sound_frequency = 1000  # 声音频率
        self.sound_duration = 1000   # 声音持续时间(毫秒)
        
        # 性能统计
        self.stats = {
            "total_checks": 0,
            "total_reminders": 0,
            "last_check_time": None,
            "start_time": None
        }
    
    def start(self):
        """启动提醒服务线程"""
        if self.is_running:
            self.logger.warning("提醒服务已经在运行")
            return False
        
        self.is_running = True
        self.stats["start_time"] = datetime.now()
        
        self.reminder_thread = threading.Thread(
            target=self._run_reminder_loop, 
            daemon=True,
            name="ReminderService"
        )
        self.reminder_thread.start()
        self.logger.info(f"提醒服务已启动，检查间隔: {self.check_interval}秒")
        return True
    
    def stop(self):
        """停止提醒服务"""
        if not self.is_running:
            return
        
        self.is_running = False
        if self.reminder_thread and self.reminder_thread.is_alive():
            self.reminder_thread.join(timeout=5)  # 等待线程结束，最多5秒
        self.logger.info("提醒服务已停止")
    
    def set_check_interval(self, interval_seconds):
        """设置检查间隔"""
        if 10 <= interval_seconds <= 3600:  # 10秒到1小时之间
            old_interval = self.check_interval
            self.check_interval = interval_seconds
            self.logger.info(f"提醒检查间隔从 {old_interval}秒 改为 {interval_seconds}秒")
            return True
        else:
            self.logger.warning(f"无效的检查间隔: {interval_seconds}秒，必须在10-3600秒之间")
            return False
    
    def enable_sound(self, enabled):
        """启用或禁用声音提醒"""
        self.sound_enabled = enabled
        status = "启用" if enabled else "禁用"
        self.logger.info(f"声音提醒已{status}")
    
    def set_sound_parameters(self, frequency=1000, duration=1000):
        """设置声音参数"""
        self.sound_frequency = frequency
        self.sound_duration = duration
        self.logger.info(f"声音参数设置: 频率={frequency}Hz, 时长={duration}ms")
    
    def _run_reminder_loop(self):
        """提醒服务主循环"""
        self.logger.info(f"提醒服务线程开始运行，检查间隔: {self.check_interval}秒")
        
        # 初始延迟，让系统有足够时间启动
        time.sleep(2)
        
        while self.is_running:
            try:
                self._check_reminders()
                
                # 休眠指定间隔
                sleep_interval = self.check_interval
                for i in range(sleep_interval):
                    if not self.is_running:
                        break
                    time.sleep(1)
                    
            except Exception as e:
                self.logger.error(f"提醒服务运行出错: {e}")
                # 出错后休眠一个完整周期，避免频繁出错
                time.sleep(self.check_interval)
    

    def _check_reminders(self):
        """检查并触发需要提醒的日程"""
        try:
            # 使用字符串方式避免循环导入
            if hasattr(self.db_manager, 'get_upcoming_schedules'):
                now = datetime.now()
                
                # 获取未来一段时间内需要提醒的日程
                check_horizon_minutes = max(self.check_interval // 60, 5)  # 至少5分钟
                upcoming_schedules = self.db_manager.get_upcoming_schedules(hours=check_horizon_minutes/60)
                
                triggered_count = 0
                for schedule in upcoming_schedules:
                    if self._process_schedule_reminder(schedule, now):
                        triggered_count += 1
                
                if triggered_count > 0:
                    self.logger.info(f"本次检查触发了 {triggered_count} 个提醒")
                    
        except Exception as e:
            self.logger.error(f"检查提醒时出错: {e}")    

    def _process_schedule_reminder(self, schedule, current_time):
        """处理单个日程的提醒逻辑"""
        schedule_id = schedule['id']
        
        # 如果已经提醒过，跳过
        if schedule_id in self.pending_reminders:
            return False
        
        # 只处理待办状态的日程
        if schedule.get('status') != 'pending':
            return False
        
        # 计算提醒时间
        try:
            start_time = datetime.strptime(schedule['start_time'], '%Y-%m-%d %H:%M:%S')
            reminder_minutes = schedule.get('reminder_minutes', 15)
            reminder_time = start_time - timedelta(minutes=reminder_minutes)
            
            # 检查是否到达提醒时间
            if current_time >= reminder_time:
                self._trigger_reminder(schedule)
                return True
                
        except Exception as e:
            self.logger.error(f"处理日程 {schedule_id} 提醒时出错: {e}")
        
        return False
    
    def _trigger_reminder(self, schedule):
        """触发提醒"""
        schedule_id = schedule['id']
        
        try:
            # 标记为已提醒
            self.pending_reminders.add(schedule_id)
            self.stats["total_reminders"] += 1
            
            # 记录提醒日志
            self.db_manager.log_reminder(schedule_id)
            
            # 播放提醒声音
            if self.sound_enabled:
                self._play_reminder_sound()
            
            # 通知GUI显示提醒
            if self.gui_callback:
                self._notify_gui(schedule)
            
            self.logger.info(f"已触发日程提醒: {schedule['title']} (ID: {schedule_id})")
            
        except Exception as e:
            self.logger.error(f"触发提醒时出错: {e}")
    
    def _notify_gui(self, schedule):
        """通知GUI显示提醒"""
        try:
            # 在GUI线程中执行回调
            if hasattr(self.gui_callback, 'root') and hasattr(self.gui_callback, 'show_reminder'):
                # 如果是Tkinter GUI，使用after方法确保在主线程执行
                self.gui_callback.root.after(0, lambda: self.gui_callback.show_reminder(schedule))
            elif callable(self.gui_callback):
                # 直接调用回调函数
                self.gui_callback(schedule)
            else:
                self.logger.warning("无效的GUI回调")
                
        except Exception as e:
            self.logger.error(f"调用GUI提醒回调失败: {e}")
    
    def _play_reminder_sound(self):
        """播放提醒声音 - 跨平台版本（增强兼容性）"""
        try:
            if sys.platform == "win32":
                # Windows系统使用winsound
                try:
                    import winsound
                    winsound.Beep(self.sound_frequency, self.sound_duration)
                    return
                except (ImportError, RuntimeError):
                    pass  # 降级到通用方法
            
            # 通用方法：使用系统命令
            if sys.platform == "darwin":
                # macOS系统
                os.system("afplay /System/Library/Sounds/Ping.aiff 2>/dev/null &")
            elif sys.platform.startswith("linux"):
                # Linux系统
                success = False
                # 尝试多种方法
                for cmd in [
                    f"beep -f {self.sound_frequency} -l {self.sound_duration}",
                    f"play -n synth {self.sound_duration/1000} sine {self.sound_frequency}",
                    "echo -e '\\a'"
                ]:
                    try:
                        os.system(f"{cmd} 2>/dev/null &")
                        success = True
                        break
                    except:
                        continue
            else:
                # 其他平台使用终端响铃
                print("\a")
                
        except Exception as e:
            self.logger.debug(f"播放提醒声音失败: {e}")  # 改为debug级别，避免烦扰用户
            
    def mark_reminder_completed(self, schedule_id):
        """标记提醒已完成处理"""
        if schedule_id in self.pending_reminders:
            self.pending_reminders.remove(schedule_id)
            self.logger.debug(f"提醒标记为已完成: {schedule_id}")
            return True
        return False
    
    def clear_pending_reminders(self):
        """清除所有待处理提醒"""
        count = len(self.pending_reminders)
        self.pending_reminders.clear()
        self.logger.info(f"已清除 {count} 个待处理提醒")
        return count
    
    def get_pending_reminders_count(self):
        """获取待处理提醒数量"""
        return len(self.pending_reminders)
    
    def get_pending_reminders(self):
        """获取待处理提醒的日程ID列表"""
        return list(self.pending_reminders)
    
    def get_service_stats(self):
        """获取服务统计信息"""
        uptime = None
        if self.stats["start_time"]:
            uptime = datetime.now() - self.stats["start_time"]
            uptime = str(uptime).split('.')[0]  # 去掉微秒部分
        
        stats = self.stats.copy()
        stats["is_running"] = self.is_running
        stats["check_interval"] = self.check_interval
        stats["pending_reminders"] = self.get_pending_reminders_count()
        stats["uptime"] = uptime
        stats["sound_enabled"] = self.sound_enabled
        
        return stats
    
    def is_alive(self):
        """检查提醒服务是否在运行"""
        return self.is_running and self.reminder_thread and self.reminder_thread.is_alive()


class ReminderManager:
    """
    提醒管理器
    提供更高级的提醒管理功能，可以管理多个提醒服务实例
    """
    
    def __init__(self, db_manager):
        self.db_manager = db_manager
        self.reminder_services = {}  # 可以管理多个提醒服务实例
        self.logger = logging.getLogger(__name__)
    
    def create_reminder_service(self, service_id="default", gui_callback=None):
        """创建提醒服务实例"""
        if service_id in self.reminder_services:
            self.logger.warning(f"提醒服务 {service_id} 已存在，将覆盖")
        
        service = ReminderService(self.db_manager, gui_callback)
        self.reminder_services[service_id] = service
        self.logger.info(f"创建提醒服务: {service_id}")
        return service
    
    def get_reminder_service(self, service_id="default"):
        """获取提醒服务实例"""
        return self.reminder_services.get(service_id)
    
    def start_all_services(self):
        """启动所有提醒服务"""
        started_count = 0
        for service_id, service in self.reminder_services.items():
            if not service.is_alive():
                if service.start():
                    started_count += 1
                    self.logger.info(f"启动提醒服务: {service_id}")
        
        self.logger.info(f"成功启动 {started_count} 个提醒服务")
        return started_count
    
    def stop_all_services(self):
        """停止所有提醒服务"""
        stopped_count = 0
        for service_id, service in self.reminder_services.items():
            if service.is_alive():
                service.stop()
                stopped_count += 1
                self.logger.info(f"停止提醒服务: {service_id}")
        
        self.logger.info(f"成功停止 {stopped_count} 个提醒服务")
        return stopped_count
    
    def get_service_status(self):
        """获取所有提醒服务状态"""
        status = {}
        for service_id, service in self.reminder_services.items():
            status[service_id] = {
                'is_running': service.is_alive(),
                'pending_reminders': service.get_pending_reminders_count(),
                'check_interval': service.check_interval,
                'stats': service.get_service_stats()
            }
        return status
    
    def get_default_service(self):
        """获取默认提醒服务"""
        return self.get_reminder_service("default")


# 测试函数
def test_reminder_service():
    """测试提醒服务"""
    import tempfile
    
    print("测试提醒服务...")
    
    # 创建临时数据库
    temp_db = tempfile.NamedTemporaryFile(delete=False, suffix='.db')
    temp_db.close()
    
    try:
        from database import DatabaseManager
        
        # 初始化数据库
        db_manager = DatabaseManager(temp_db.name)
        
        # 创建测试日程（1分钟后开始）
        test_time = (datetime.now() + timedelta(minutes=1)).strftime("%Y-%m-%d %H:%M:%S")
        schedule_id = db_manager.add_schedule(
            title="测试提醒",
            start_time=test_time,
            description="这是一个测试提醒",
            reminder_minutes=0  # 立即提醒
        )
        
        print(f"创建测试日程，ID: {schedule_id}")
        
        # 创建提醒管理器
        reminder_manager = ReminderManager(db_manager)
        
        # 创建提醒服务
        def test_callback(schedule):
            print(f"🎯 收到提醒: {schedule['title']}")
            print(f"   时间: {schedule['start_time']}")
            print(f"   描述: {schedule.get('description', '无')}")
        
        reminder_service = reminder_manager.create_reminder_service("test", test_callback)
        reminder_service.set_check_interval(10)  # 10秒检查一次
        reminder_service.enable_sound(False)  # 测试时禁用声音
        
        # 启动服务
        reminder_service.start()
        
        print("提醒服务已启动，等待提醒...")
        print("按Ctrl+C停止测试")
        
        try:
            # 运行一段时间
            for i in range(12):  # 2分钟
                if not reminder_service.is_alive():
                    print("提醒服务意外停止")
                    break
                
                time.sleep(10)
                stats = reminder_service.get_service_stats()
                print(f"检查 #{stats['total_checks']}, 提醒: #{stats['total_reminders']}, 待处理: {stats['pending_reminders']}")
                
        except KeyboardInterrupt:
            print("\n用户中断测试")
        
        finally:
            reminder_service.stop()
            
    except Exception as e:
        print(f"测试失败: {e}")
        import traceback
        traceback.print_exc()
    finally:
        # 清理临时文件
        if os.path.exists(temp_db.name):
            os.unlink(temp_db.name)
    
    print("测试完成")


if __name__ == "__main__":
    # 配置日志
    logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    # 测试提醒服务
    test_reminder_service()